#include <bits/stdc++.h>
using namespace std;

#define LL long long

#define CLR(i, a) memset(i, a, sizeof(i))

const int MAXN = 20 + 5;
const int MAXM = 2e4 + 5;

const int N = 20; // 最大步长B的值，用于矩阵维度

// 矩阵结构体，用于矩阵快速幂
struct Matrix {
  bool a[MAXN][MAXN]; // 布尔型矩阵，存储转移关系

  // 初始化矩阵为零矩阵
  Matrix() { CLR(a, 0); }

  // 重载矩阵乘法运算符，使用逻辑运算替代普通乘法
  // C[i][j] = OR(A[i][k] AND B[k][j])
  Matrix operator*(const Matrix &t) const {
    Matrix res;
    for (int k = 1; k <= N; ++k)
      for (int i = 1; i <= N; ++i)
        for (int j = 1; j <= N; ++j) {
          res.a[i][j] |= a[i][k] & t.a[k][j];
        }
    return res;
  }
};

// 预处理的转移矩阵
Matrix M_G, M_B;               // 好格子和坏格子的基本转移矩阵
Matrix M_G_pw[41], M_B_pw[41]; // 预处理M_G和M_B的2^i次幂
LL l[MAXM], r[MAXM];           // 存储坏格子区间的左右端点
bool f[MAXN], new_f[MAXN];     // 当前状态向量和新状态向量

// 应用矩阵的n次幂到当前状态向量f
// type = 1 表示应用好格子转移矩阵M_G的n次幂
// type = 0 表示应用坏格子转移矩阵M_B的n次幂
void apply(int type, LL n) {
  for (int i = 0; i <= 40; ++i) {
    if ((n >> i) & 1) {                // 快速幂分解，如果n的第i位为1
      memset(new_f, 0, sizeof(new_f)); // 清空新状态向量
      // 矩阵乘以向量的操作
      for (int x = 1; x <= N; ++x)
        for (int y = 1; y <= N; ++y) {
          // new_f[x] |= A[x][y] & f[y]
          new_f[x] |= (type ? M_G_pw[i] : M_B_pw[i]).a[x][y] & f[y];
        }
      for (int x = 1; x <= N; ++x)
        f[x] = new_f[x]; // 更新状态向量
    }
  }
}

int main() {
  LL n;        // 总共的格子数
  int m, a, b; // m个坏格子区间，步长范围[a,b]
  scanf("%lld%d%d%d", &n, &m, &a, &b);
  for (int i = 1; i <= m; ++i)
    scanf("%lld%lld", l + i, r + i); // 读入坏格子区间

  // 构造好格子的转移矩阵M_G
  // 第一行：可以走a到b步到达第一个位置
  for (int i = a; i <= b; ++i)
    M_G.a[1][i] = 1;
  // 其他行：表示状态的转移
  for (int i = 2; i <= N; ++i)
    M_G.a[i][i - 1] = 1;

  // 构造坏格子的转移矩阵M_B
  // 只有状态转移，没有新的可达位置
  for (int i = 2; i <= N; ++i)
    M_B.a[i][i - 1] = 1;

  // 预处理矩阵的2^i次幂，用于快速幂
  M_G_pw[0] = M_G;
  M_B_pw[0] = M_B;

  // 计算更高次幂的矩阵  M_G_pw[i] : M_G^{2^i} 预处理
  //为了加速多次矩阵乘法运算，代码预先计算了 M_G 和 M_B 的各次幂（最高到 $2^{40}$ 次幂），并保存在 M_G_pw[] 和 M_B_pw[] 数组中。
  //这样可以在后续快速幂算法中直接复用这些预处理结果，显著提升性能。
  for (int i = 1; i <= 40; ++i) {
    M_G_pw[i] = M_G_pw[i - 1] * M_G_pw[i - 1];
    M_B_pw[i] = M_B_pw[i - 1] * M_B_pw[i - 1];
  }

  f[1] = 1;   // 初始状态：第一个位置可达
  LL now = 1; // 当前所在位置

  // 按顺序处理每个坏格子区间
  for (int i = 1; i <= m; ++i) {

    // [now+1, l[i]-1] 都是好格子，应用好格子转移矩阵
    if (l[i] - 1 - now > 0)
      apply(1, l[i] - 1 - now);

    // [l[i], r[i]] 都是坏格子，应用坏格子转移矩阵
    apply(0, r[i] - l[i] + 1);
    
    now = r[i]; // 更新当前位置
  }

  // 处理最后剩余的好格子区间 [now+1, n]
  if (n - now > 0)
    apply(1, n - now);

  // 输出结果：第一个位置是否可达（即是否能到达终点）
  puts(f[1] ? "Yes" : "No");

  return 0;
}